package com.zh.opcua.milo;

import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem;
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription;
import org.eclipse.milo.opcua.stack.core.AttributeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemCreateRequest;
import org.eclipse.milo.opcua.stack.core.types.structured.MonitoringParameters;
import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;


/**
 * Copyright (C) 广州中和互联网技术有限公司
 *
 * @author 范家微 fanjiawei@borche.cn
 * @date :2020/12/18 14:29
 */
public class MiloSubscribe {
	public static List<UaMonitoredItem> createSubscription(OpcUaClient opcUaClient) throws ExecutionException, InterruptedException {
		// 创建连接
		opcUaClient.connect().get();

		// 创建发布间隔1000ms的订阅 对象
		UaSubscription subscription = opcUaClient.getSubscriptionManager().createSubscription(10.0).get();

		// 创建需要订阅的变量
		NodeId nodeId = new NodeId(2, "数据类型示例.16 位设备.R 寄存器.Double1");
		ReadValueId readValueId = new ReadValueId(nodeId, AttributeId.Value.uid(), null, null);


		// 创建监控的参数
		MonitoringParameters parameters = new MonitoringParameters(UInteger.valueOf(1),
				//采样间隔
				10.0,
				null, //filter ,null 表示默认
				UInteger.valueOf(10),//队列尺寸
				true //丢弃最旧的
		);

		// 创建监控项请求
		// 该请求最后用于创建订阅
		MonitoredItemCreateRequest request = new MonitoredItemCreateRequest(readValueId, MonitoringMode.Reporting, parameters);

		ArrayList<MonitoredItemCreateRequest> requests = new ArrayList<>();
		requests.add(request);

		// 创建监控项，并且注册变量值改变时候的回调函数
		List<UaMonitoredItem> items = subscription.createMonitoredItems(TimestampsToReturn.Both, requests, (item, id) -> {
			//这个回调函数就是该变量每次发生改变后所调用的方法，这里的例子是变量改变时打印节点id和变量值到标准输出中。
			item.setValueConsumer((item1, value) -> {
				System.out.println("nodeId :" + item1.getReadValueId().getNodeId());
				System.out.println("value:" + value.getValue().getValue());
			});

		}).get();


		System.out.println(Thread.currentThread());
		CompletableFuture<OpcUaClient> future = new CompletableFuture<>();
		future.complete(opcUaClient);
		Thread.sleep(999999999L);
//		// 循环改变server中的值
//		for (int i = 0; i < 500; i++) {
//			Thread.sleep(50);
//			//写数据
//			// 1.创建节点
//			NodeId stringNode = new NodeId(2, "通道 2.设备 1.TAG5");
//
//			// 2.创建Variant对象和DataValue对象
//			Variant variant = new Variant("上山打"+i+"只老虎");
//			DataValue dataValue1 = new DataValue(variant, null, null);
//			// 3.获取返回状态
//			StatusCode statusCode = StatusCode.BAD;
//			try {
//				statusCode = opcUaClient.writeValue(stringNode, dataValue1).get();
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//			System.out.println("状态是"+statusCode.isGood());
//		}
		return items;

	}
}
